using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Drawing;
using System.Collections;
using System.Data;
using System.Text;
using System.Drawing.Printing;

namespace PrintDataGrid
{
    public class PrintHoSo
    {
        public const String PAGE_BREAK = "PAGE BREAK";

        private StringFormat StrFormat;  // Holds content of a TextBox Cell to write by DrawString
        private StringFormat StrFormatComboBox; // Holds content of a Boolean Cell to write by DrawImage
        private bool NewPage;            // Indicates if a new page reached
        private int PageNo;              // Number of pages to print
        private PrintDocument printDoc = new PrintDocument();  // PrintDocumnet Object used for printing
        // setting
        private String title;
        private List<String> lTxt, lFields;

        private String imgPath;
        private Font tilteFont, bodyFont;
        private int lIndex;
        private bool landscape;

        public PrintHoSo()
        {
            //CellButton = new Button();
            lTxt = new List<string>();
            lFields = new List<string>();
            tilteFont = new Font("Times New Roman", 22, FontStyle.Bold | FontStyle.Italic);
            bodyFont = new Font("Arial", 10);

            imgPath = "";
            lIndex = 0;
        }

        public String Title
        {
            get { return title; }
            set { title = value; }
        }

        public Font TitleFont
        {
            get { return tilteFont; }
            set { tilteFont = value; }
        }

        public Font ContentFont
        {
            get { return bodyFont; }
            set { bodyFont = value; }
        }

        public bool LanscapeMode
        {
            get { return landscape; }
            set { landscape = value; }
        }

        public void addField(String field_, String text_)
        {
            if (field_.Length > 0 && !(field_ == PAGE_BREAK))
                lFields.Add(field_ + ": ");
            else
                lFields.Add(field_);
            lTxt.Add(text_);
        }

        public void setImage(String _imagePath)
        {
            // Set Image for print page
            /*
             * xxxxxxxxxxxxxxxxxxxx|-----|
             * xxxxxxxxxxxxxxxxxxxx|  I  |
             * xxxxxxxxxxxxxxxxxxxx|  M  |
             * xxxxxxxxxxxxxxxxxxxx|  G  |
             * xxxxxxxxxxxxxxxxxxxx|-----|
             * xxxxxxxxxxxxxxxxxxxxxxxxxx
             * xxxxxxxxxxxxxxxxxxxxxxxxxx
             * xxxxxxxxxxxxxxxxxxxxxxxxxx
             * xxxxxxxxxxxxxxxxxxxxxxxxxx
             */
            imgPath = _imagePath;
        }

        private int getMaxFieldWith(Graphics g, Font f)
        {
            int result = 0;
            for (int i = 0; i < lFields.Count; i++)
            {
                int w = (int)g.MeasureString(lFields[i], f).Width;
                if (w > result)
                    result = w;
            }

            return result;
        }

        public void Show()
        {
            // show print preview
            try
            {
                PrintPreviewDialog ppvw = new PrintPreviewDialog();
                ppvw.Document = printDoc;

                // Showing the Print Preview Page
                printDoc.BeginPrint += new System.Drawing.Printing.PrintEventHandler(PrintDoc_BeginPrint);
                printDoc.PrintPage += new System.Drawing.Printing.PrintPageEventHandler(PrintDoc_PrintPage);

                printDoc.DefaultPageSettings.Landscape = landscape;

                if (ppvw.ShowDialog() != DialogResult.OK)
                {
                    printDoc.BeginPrint -= new System.Drawing.Printing.PrintEventHandler(PrintDoc_BeginPrint);
                    printDoc.PrintPage -= new System.Drawing.Printing.PrintPageEventHandler(PrintDoc_PrintPage);
                    return;
                }

                // Printing the Documnet
                printDoc.Print();
                printDoc.BeginPrint -= new System.Drawing.Printing.PrintEventHandler(PrintDoc_BeginPrint);
                printDoc.PrintPage -= new System.Drawing.Printing.PrintPageEventHandler(PrintDoc_PrintPage);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Lỗi: " + ex.Message);
            }
        }

        private void PrintDoc_BeginPrint(object sender, System.Drawing.Printing.PrintEventArgs e) 
        {
            try
	        {
                // Formatting the Content of Text Cell to print
                StrFormat = new StringFormat();
                StrFormat.Alignment = StringAlignment.Near;
                StrFormat.LineAlignment = StringAlignment.Center;
                StrFormat.Trimming = StringTrimming.EllipsisCharacter;

                // Formatting the Content of Combo Cells to print
                StrFormatComboBox = new StringFormat();
                StrFormatComboBox.LineAlignment = StringAlignment.Center;
                StrFormatComboBox.FormatFlags = StringFormatFlags.NoWrap;
                StrFormatComboBox.Trimming = StringTrimming.EllipsisCharacter;

                PageNo = 1;
                NewPage = true;
     		
	        }
	        catch (Exception ex)
	        {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);        		
	        }
        }

        private int DrawTextBox(Graphics g, String _text, int _with, int _top, int _left)
        {
            int newTop = 0;
            String[] word = _text.Split(' ');
            int i = 0;
            String tmp = "";
            while (i < word.Length)
            {
                if (g.MeasureString(tmp + " " + word[i], bodyFont).Width <= _with)
                {
                    tmp += " " + word[i];
                    i++;
                }
                else
                {
                    if (tmp.Length == 0)
                    {
                        // string is bigger than width
                        float y = 0;
                        for (int j = 0; j < word[i].Length; j++)
                        {
                            y += g.MeasureString(word[i][j].ToString(), bodyFont).Width;
                            if (y >= _with)
                            {
                                y = 0;
                                newTop += (int)g.MeasureString(word[i][j].ToString(), bodyFont).Height;
                            }
                        }
                        i++;
                    }
                    else
                    {
                        newTop += (int)g.MeasureString(tmp, bodyFont).Height;
                        tmp = "";
                    }
                }
            }

            if (tmp.Length > 0)
                newTop += (int)g.MeasureString(tmp, bodyFont).Height + 5;
            g.DrawString(_text, bodyFont, Brushes.Black, new RectangleF(_left, _top, _with, newTop));// y + _left, newTop);

            return newTop;
        }

        private void PrintDoc_PrintPage(object sender, 
                    System.Drawing.Printing.PrintPageEventArgs e) 
        {
            int tmpTop = e.MarginBounds.Top;
            int tmpLeft = e.MarginBounds.Left;

            try
            {
                #region draw titile on first page
                if (PageNo == 1)
                {
                    // Titile of print
                    if (title.Length > 0)
                    {
                        e.Graphics.DrawString(title,
                                              TitleFont,
                                              Brushes.Black,
                                              (e.PageBounds.Width - e.Graphics.MeasureString(title, TitleFont, e.MarginBounds.Width).Width) / 2, // Center 
                                              e.MarginBounds.Top);
                        tmpTop += (int)(e.Graphics.MeasureString(title, TitleFont, e.MarginBounds.Width).Height + 13);
                    }

                    if (imgPath.Length > 0) 
                    {
                        e.Graphics.DrawImage(Image.FromFile(imgPath), e.MarginBounds.Right - 200, tmpTop,
                                                                        120, 160);
                    }

                }
                #endregion
                int fieldWith = getMaxFieldWith(e.Graphics, bodyFont) + 10;

                for (int i = lIndex; i < lTxt.Count; i++)
                {
                    if (tmpTop >= e.MarginBounds.Height + e.MarginBounds.Top)
                    {
                        DrawFooter(e, PageNo);
                        PageNo++;
                        e.HasMorePages = true;
                        lIndex = i;
                        return;
                    }
                    else
                    {
                        if (lFields[i] == PAGE_BREAK)
                        {
                            DrawFooter(e, PageNo);
                            PageNo++;
                            e.HasMorePages = true;
                            lIndex = i + 1;
                            return;
                        }
                        // draw field
                        int fw = (int)e.Graphics.MeasureString(lFields[i], bodyFont).Width;
                        int h1 = DrawTextBox(e.Graphics, lFields[i], fieldWith, tmpTop, tmpLeft);
                        // draw text
                        int h2 = DrawTextBox(e.Graphics, lTxt[i], 350, tmpTop, tmpLeft + fieldWith);
                        tmpTop += ((h1 > h2) ? h1 : h2) + 5;
                    }
                }

                e.HasMorePages = false;
	        }
	        catch (Exception ex)
	        {
                MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);        		
	        }
        }

        private void DrawFooter(System.Drawing.Printing.PrintPageEventArgs e, 
                    int pageNo)
        {
            String t = "Trang " + pageNo;
            e.Graphics.DrawString(t, bodyFont, Brushes.Black, 
                e.MarginBounds.Left + (e.MarginBounds.Width - 
                e.Graphics.MeasureString(t, bodyFont, e.MarginBounds.Width).Width) / 2, 
                e.MarginBounds.Top + e.MarginBounds.Height + 31);
        }
    }
}
